﻿
// opencv_mfcDlg.cpp: 实现文件
//
//#include "stdafx.h"
#include "pch.h"
#include "framework.h"
#include "opencv_mfc.h"
#include "opencv_mfcDlg.h"
#include "afxdialogex.h"
#include <Dbt.h>
#include <opencv2\opencv.hpp> 
#include <highgui/highgui.hpp>
#include <imgproc/imgproc.hpp>

CFont   font;

using namespace cv;
using namespace std;

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CopencvmfcDlg 对话框



CopencvmfcDlg::CopencvmfcDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_OPENCV_MFC_DIALOG, pParent)
	, m_num(0)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CopencvmfcDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_STATICMessage, m_num);
}

BEGIN_MESSAGE_MAP(CopencvmfcDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
//	ON_WM_DEVMODECHANGE()
ON_MESSAGE(WM_DEVICECHANGE, &CopencvmfcDlg::OnDevicechange)
ON_BN_CLICKED(IDCANCEL, &CopencvmfcDlg::OnBnClickedCancel)
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()


// CopencvmfcDlg 消息处理程序

BOOL CopencvmfcDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	//设置static text
	font.CreatePointFont(258, _T("微软雅黑"));
	GetDlgItem(IDC_STATICMessage)->SetFont(&font);

#pragma region 读取配置文件
	try
	{
		CString strTime = CTime::GetCurrentTime().Format("%Y%m%d");

		//路径，我用的根目录是"c:"，你可以根据自己需要修改，
		//如果就是程序当前的目录，则用相对路径，直接写文件夹的名称
		CString strPath = L"./" + strTime;

		m_num = GetPrivateProfileInt(L"INFO", L"n_num", 1, strPath + L"/INFO.ini");
		strTemp.Format(L"%d", m_num);
		GetDlgItem(IDC_STATICMessage)->SetWindowTextW(strTemp);
		UpdateData();

	}
	catch (const std::exception&)
	{
		;
	}
	
#pragma endregion


	//ShowWindow(SW_MAXIMIZE);
	ShowWindow(SW_NORMAL);
	//ShowWindow(SW_MINIMIZE);

	// TODO: 在此添加额外的初始化代码
	static const GUID GUID_DEVINTERFACE_LIST[] =
		
	{ 
		// GUID_DEVINTERFACE_USB_DEVICE
		{0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED }},

		// GUID_DEVINTERFACE_DISK
		{ 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } },

		// GUID_DEVINTERFACE_HID, 
		{ 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },

		// GUID_NDIS_LAN_CLASS
		{ 0xad498944, 0x762f, 0x11d0, { 0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3, 0x35, 0x8c } },

		// GUID_DEVINTERFACE_COMPORT
		{ 0x86e0d1e0, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73 } },

		//GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
	   { 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },

	   // GUID_DEVINTERFACE_PARALLEL
	   { 0x97F76EF0, 0xF883, 0x11D0, { 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x5C } },

	   //GUID_DEVINTERFACE_PARCLASS
	  { 0x811FC6A5, 0xF728, 0x11D0, { 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75, 0x3E, 0xD1 } }



	};

	
	HDEVNOTIFY hDevNotify;
	DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
	//ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
	NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
	NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
	for (int i = 0; i < sizeof(GUID_DEVINTERFACE_LIST) / sizeof(GUID); i++)
	{
		NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];
		hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
		if (!hDevNotify)
		{
			AfxMessageBox(CString("Can't register device notification: ")
				+ _com_error(GetLastError()).ErrorMessage(), MB_ICONEXCLAMATION);
			return FALSE;
		}
	}

	MessageBoxW(L"请插入或重新插入摄像头...", L"开始测试了吗?", 0);
	return TRUE;
}



// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CopencvmfcDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CopencvmfcDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



//void CopencvmfcDlg::OnDevModeChange(LPTSTR lpDeviceName)
//{
//	CDialogEx::OnDevModeChange(lpDeviceName);
//
//	// TODO: 在此处添加消息处理程序代码
//}


afx_msg LRESULT CopencvmfcDlg::OnDevicechange(WPARAM wParam, LPARAM lParam)
{
	if (DBT_DEVICEARRIVAL == wParam /*|| DBT_DEVICEREMOVECOMPLETE == wParam*/) {
		PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
		PDEV_BROADCAST_DEVICEINTERFACE pDevInf;
		PDEV_BROADCAST_HANDLE pDevHnd;
		PDEV_BROADCAST_OEM pDevOem;
		PDEV_BROADCAST_PORT pDevPort;
		PDEV_BROADCAST_VOLUME pDevVolume;

		//根据窗口标题获得窗口句柄  L"camera2.cpp-记事本"

		HWND hWnd = ::FindWindow(NULL,LPCWSTR(L"Audacity") );
		switch (pHdr->dbch_devicetype) {
		case DBT_DEVTYP_DEVICEINTERFACE:
		{
			/*AfxMessageBox(CString("Can't register device notification: ")
				+ _com_error(GetLastError()).ErrorMessage(), MB_ICONEXCLAMATION);*/
				//获取窗口标题
		

			Sleep(450);
#pragma region 打开摄像头并检测清晰度
			try
			{
				Mat imageSobel;
				Mat imageGrey;
				Mat frame;

				VideoCapture capture(0);//读取视摄像头实时画面数据，0默认是笔记本的摄像头；如果是外接摄像头，这里改为1

				namedWindow("Camera", 0);  //1为自动大小,0为可调节

#pragma region 摄像头参数
				//cvResizeWindow("Camera", 640, 480); //窗口大小设置
				//resizeWindow("Camera", 1024, 768);


				capture.set(CV_CAP_PROP_FRAME_WIDTH, 640);//宽度 
				capture.set(CV_CAP_PROP_FRAME_HEIGHT, 480);//高度
				capture.set(CV_CAP_PROP_FPS, 30);//帧率 帧/秒
				//capture.set(CV_CAP_PROP_BRIGHTNESS, 1);//亮度 1
				//capture.set(CV_CAP_PROP_CONTRAST, 40);//对比度 40
				//capture.set(CV_CAP_PROP_SATURATION, 50);//饱和度 50
				//capture.set(CV_CAP_PROP_HUE, 50);//色调 50
				//capture.set(CV_CAP_PROP_EXPOSURE, 50);//曝光 50

				/*获取摄像头参数

					1 capture.get(CV_CAP_PROP_FRAME_WIDTH);
				2 capture.get(CV_CAP_PROP_FRAME_HEIGHT);
				3 capture.get(CV_CAP_PROP_FPS);
				4 capture.get(CV_CAP_PROP_BRIGHTNESS);
				5 capture.get(CV_CAP_PROP_CONTRAST);
				6 capture.get(CV_CAP_PROP_SATURATION);
				7 capture.get(CV_CAP_PROP_HUE);
				8 capture.get(CV_CAP_PROP_EXPOSURE);*/
#pragma endregion

				// 写入配置文件中,显示
				m_num++;
#pragma region 得到产量后,显示在text中,再写入当前日期中的ini文件中
				strTemp.Format(L"%d", m_num);
				GetDlgItem(IDC_STATICMessage)->SetWindowTextW(strTemp);

				// 获得当前时间并格式化为字符串
				CString strTime = CTime::GetCurrentTime().Format("%Y%m%d");
				//路径，我用的根目录是"c:"，你可以根据自己需要修改，
				//如果就是程序当前的目录，则用相对路径，直接写文件夹的名称
				CString strPath = L"./" + strTime;
				//建立文件夹
				CreateDirectory(strPath, NULL);
				strTemp.Format(L"%d", m_num);
				::WritePrivateProfileString(L"INFO", L"n_num", strTemp, strPath + L"/INFO.ini");
#pragma endregion

				
				
				for (int i = 0; i < 1; i++)
				{
					Sleep(50);
					//发送键盘按下，此处模拟F5键

					/*::PostMessage(hWnd, WM_KEYDOWN, VK_F5, 1);*/
					::PostMessage(hWnd, WM_KEYDOWN, VK_SPACE, 1);

					Sleep(50);

					//发送键盘弹起

					::PostMessage(hWnd, WM_KEYUP, VK_SPACE, 1);


				}
				while (true)
				{
					if (waitKey(1) == VK_ESCAPE)   //延时20ms,获取用户是否按键的情况，如果按下q，会推出程序 
						break;

					capture >> frame;            //读取当前帧
					if (!frame.empty()) {          //判断输入的视频帧是否为空的

						cvtColor(frame, imageGrey, CV_RGB2GRAY);

						//Laplacian(imageGrey, imageSobel, CV_16U);   cv2.CV_64F
						//图像的平均灰度
						Laplacian(imageGrey, imageSobel, CV_16U);
						double meanValue = 0.0;
						meanValue = mean(imageSobel)[0];

						//double to string
						stringstream meanValueStream;
						string meanValueString;
						meanValueStream << meanValue;
						meanValueStream >> meanValueString;
						meanValueString = meanValueString;    //640,480
						putText(frame, meanValueString, Point(500, 470), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 0), 1);
						if (meanValue > 9.1)
						{
							putText(frame, "OK", Point(490, 90), CV_FONT_HERSHEY_COMPLEX, 3, Scalar(0, 255, 0), 4);

						}
						imshow("Camera", frame);
					}
					else
					{
						return -1;
					}
					

				}


				//
			}
			catch (const std::exception&)
			{
				cvDestroyWindow("camera");
				//PostMessage(WM_QUIT, 0, 0);//最常用
				break;
			}


#pragma endregion
		}
		
		break;

		case DBT_DEVTYP_HANDLE:
			pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
			break;

		case DBT_DEVTYP_OEM:
			pDevOem = (PDEV_BROADCAST_OEM)pHdr;
			break;

		case DBT_DEVTYP_PORT:
			pDevPort = (PDEV_BROADCAST_PORT)pHdr;
			break;

		case DBT_DEVTYP_VOLUME:
			pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
			break;
		}
	}
	else if (DBT_DEVICEREMOVECOMPLETE == wParam)
	{
		cvDestroyWindow("camera");
		

	}
	return 0;
}


void CopencvmfcDlg::OnBnClickedCancel()
{
	
	m_num = 0;
	GetDlgItem(IDC_STATICMessage)->SetWindowTextW(TEXT("0"));
	
	
}


void CopencvmfcDlg::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	
	

#pragma region 按esc键退出
	keybd_event(VK_ESCAPE, 0, 0, 0);
	keybd_event(VK_ESCAPE, 0, WM_KEYDOWN, 0);

	keybd_event(VK_ESCAPE, 0, 0, 0);
	keybd_event(VK_ESCAPE, 0, WM_KEYUP, 0);
	cvDestroyWindow("camera");
	cvDestroyAllWindows();
	CDialogEx::OnCancel();
	

#pragma endregion

	
	
}


void CopencvmfcDlg::OnDestroy()
{
	
	CDialogEx::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
}

#pragma region  文本颜色设置
HBRUSH CopencvmfcDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);

	if (pWnd->GetDlgCtrlID() == IDC_STATICMessage)
	{
		pDC->SetTextColor(RGB(0, 255, 25));
	}

	

	return hbr;
}

#pragma endregion